package crmdna.api.endpoint;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import javax.annotation.Nullable;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;

import com.google.api.server.spi.config.Api;
import com.google.appengine.api.users.User;

import crmdna.common.APIResponse;
import crmdna.common.APIResponse.Status;
import crmdna.common.RequestInfo;
import crmdna.common.StopWatch;
import crmdna.common.Utils;
import crmdna.common.contact.Contact;
import crmdna.common.contact.ContactProp;
import crmdna.common.contact.ValidationResultProp;
import crmdna.email.EmailProp;
import crmdna.email.GAEEmail;
import crmdna.gspreadsheet.GSpreadSheet;
import crmdna.participant.Participant;
import crmdna.participant.ParticipantProp;
import crmdna.participant.UploadReportProp;
import crmdna.program.Program;
import crmdna.program.ProgramProp;

@Api(name = "participant")
public class ParticipantApi {

	public APIResponse uploadFromGoogleSpreadSheet(
			@Nullable @Named("client") String client,
			@Named("publishedSpreadSheetKey") String gsKey,
			@Named("programId") long programId,
			@Nullable @Named("maxLinesDefault2500") Integer maxLines,
			@Nullable @Named("updateMemberProfileDefaultTrue") Boolean updateProfile,
			@Nullable @Named("ignoreWarningsDefaultFalse") Boolean ignoreWarnings,
			@Nullable @Named("showStackTrace") Boolean showStackTrace,			
			HttpServletRequest req, User user) {

		if (null == client)
			client = "isha";

		String login = null;

		try {
			StopWatch sw = StopWatch.createStarted();

			login = Utils.getLoginEmail(user);
			List<Map<String, String>> listOfMap = GSpreadSheet
					.getPublishedSpreasheetAsListOfMap(gsKey, maxLines);

			if (ignoreWarnings == null)
				ignoreWarnings = false;

			if (updateProfile == null)
				updateProfile = true;

			List<ContactProp> contactDetailProps = Contact
					.getContactDetailsFromListOfMap(listOfMap);

			UploadReportProp prop = Participant.uploadAll(client,
					contactDetailProps, programId, ignoreWarnings,
					updateProfile, Utils.getLoginEmail(user));

			return new APIResponse()
					.status(Status.SUCCESS)
					.object(prop)
					.processingTimeInMS(sw.msElapsed())
					.message(
							"Uploaded data for [" + prop.numParticipants
									+ "] participants");

		} catch (Exception ex) {
			return Utils.toAPIResponse(ex, showStackTrace, new RequestInfo()
					.client(client).login(login).req(req));
		}
	}

	public APIResponse validateSpreadsheet(
			@Named("spreadSheetKey") String gsKey,
			@Nullable @Named("maxLinesDefault2500") Integer maxLines,
			@Nullable @Named("showStackTrace") Boolean showStackTrace,
			HttpServletRequest req, User user) {

		try {
			StopWatch sw = StopWatch.createStarted();

			List<Map<String, String>> listOfMap = GSpreadSheet
					.getPublishedSpreasheetAsListOfMap(gsKey, maxLines);

			List<ContactProp> contactDetailProps = Contact
					.getContactDetailsFromListOfMap(listOfMap);

			//ValidationResultProp prop = Contact.validate(contactDetailProps);
			ValidationResultProp prop = Contact.validate2(contactDetailProps);

			if (prop.hasErrors())
				return new APIResponse(Status.ERROR_RESOURCE_INCORRECT, prop);

			return new APIResponse().status(Status.SUCCESS).object(prop)
					.processingTimeInMS(sw.msElapsed());

		} catch (Exception ex) {
			return new APIResponse(ex, showStackTrace, "No client", req, null);
		}
	}

	public APIResponse deleteAllParticipants(
			@Nullable @Named("client") String client,
			@Named("programId") long programId,
			@Nullable @Named("showStackTrace") Boolean showStackTrace,
			User user, HttpServletRequest req) {

		String login = null;

		try {

			StopWatch sw = StopWatch.createStarted();

			if (null == client)
				client = "isha";

			login = Utils.getLoginEmail(user);
			int numDeleted = Participant.deleteAll(client, programId, login);

			return new APIResponse().status(Status.SUCCESS)
					.processingTimeInMS(sw.msElapsed())
					.message("Deleted [" + numDeleted + "] participants");

		} catch (Exception ex) {
			return new APIResponse(ex, showStackTrace, client, req, login);
		}
	}

	public APIResponse sendParticipantListAsEmail(
			@Nullable @Named("client") String client,
			@Named("programId") long programId,
			@Nullable @Named("showStackTrace") Boolean showStackTrace,
			User user, HttpServletRequest req) {

		String login = null;

		try {

			if (null == client)
				client = "isha";

			login = Utils.getLoginEmail(user);

			List<ParticipantProp> participantProps = Participant.getAll(client,
					programId, login);

			if (participantProps.size() == 0)
				return new APIResponse()
						.status(Status.ERROR_RESOURCE_NOT_FOUND).message(
								"No participants found for program Id ["
										+ programId + "]");

			List<ContactProp> contactDetailProps = new ArrayList<>();

			for (ParticipantProp participantProp : participantProps) {
				contactDetailProps.add(participantProp.contactDetail);
			}

			Collections.sort(contactDetailProps);

			EmailProp emailProp = new EmailProp();

			ProgramProp programProp = Program.safeGet(client, programId)
					.toProp();

			emailProp.toEmailAddresses.add(login);
			emailProp.bodyHtml = programProp.getDetailsAsHtml();
			emailProp.bodyHtml += "<br><br>Participant details are attached.";

			emailProp.csvAttachmentData = Contact.getCSV(contactDetailProps);
			emailProp.sendCSVAttachment = true;
			emailProp.attachmentName = programProp.getNameWOVenue() + ".csv";
			emailProp.subject = "Participants list for program - "
					+ programProp.getNameWOVenue();

			GAEEmail.send(emailProp);

			return new APIResponse().status(Status.SUCCESS).message(
					"Email sent");

		} catch (Exception ex) {
			return new APIResponse(ex, showStackTrace, client, req, login);
		}
	}
}
